package com.levi.mall.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import com.levi.constants.MallConstants;
import com.levi.enums.EnumUtil;
import com.levi.form.CartAddForm;
import com.levi.form.CartUpdateForm;
import com.levi.mall.service.CartService;
import com.levi.mall.service.ProductService;
import com.levi.pojo.Cart;
import com.levi.pojo.Product;
import com.levi.vo.CartProductVo;
import com.levi.vo.CartVo;
import com.levi.vo.ResponseVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author shentong
 * @since 2022/3/30 10:22 PM
 */
@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private ProductService productService;

    @Autowired
    private HashOperations<String,String,String> opsForHash;

    private final Gson gson = new Gson();

    @Override
    public ResponseVo<CartVo> add(Integer uid,CartAddForm cartAddForm) {
        Integer quantity = 1;
        //1.查询数据库中是否有该商品
        Product product = productService.getById(cartAddForm.getProductId());
        if (product == null) {
            return ResponseVo.error(EnumUtil.PRODUCT_NOT_EXIST);
        }
        //2.判断该商品是否是在售状态
        if (EnumUtil.PRODUCT_STATUS_SOLD_OUT.getCode().equals(product.getStatus()) || EnumUtil.PRODUCT_STATUS_DELETED.getCode().equals(product.getStatus())) {
            return ResponseVo.error(EnumUtil.PRODUCT_SOLD_OUT_OR_DELETED);
        }
        //3.判断商品库存是否充足
        if (product.getStock() <=0) {
            return ResponseVo.error(EnumUtil.PRODUCT_STOCK_ERROR);
        }
        //4.把商品放到redis中,使用hash结构存储
        String key = String.format(MallConstants.CART_REDIS_KEY_TEMPLATE, uid);
        String value = opsForHash.get(key, String.valueOf(product.getId()));
        Cart cart;
        if (StringUtils.isBlank(value)) {
            //如果redis里没有添加该商品则直接添加
            cart = new Cart(product.getId(), quantity, cartAddForm.getSelected());
        }else{
            //如果有该商品则数量+1
            cart = gson.fromJson(value, Cart.class);
            cart.setQuantity(cart.getQuantity() + quantity);
        }
        opsForHash.put(key,
                String.valueOf(cartAddForm.getProductId()),
                gson.toJson(cart));
        //添加完购物车之后返回购物车中的商品信息
        return cartList(uid);
    }

    @Override
    public ResponseVo<CartVo> cartList(Integer uid) {

        String key = String.format(MallConstants.CART_REDIS_KEY_TEMPLATE, uid);
        //遍历redis中的hash结构数据
        Map<String, String> entries = opsForHash.entries(key);
        Set<Integer> productIdSet = new HashSet<>();
        for (Map.Entry<String, String> entry : entries.entrySet()) {
            Integer productId = Integer.parseInt(entry.getKey());
            productIdSet.add(productId);
        }
        LambdaQueryWrapper<Product> ew = new LambdaQueryWrapper<>();
        ew.in(!CollectionUtils.isEmpty(productIdSet),Product::getId, productIdSet);
        List<Product> productList = productService.list(ew);
        CartVo cartVo = setProductVoParam(key, productList);
        return ResponseVo.success(cartVo);
    }

    private CartVo setProductVoParam(String key, List<Product> productList) {
        CartVo cartVo = new CartVo();
        List<CartProductVo> cartProductVoList = new ArrayList<>();
        boolean selectAll = true;
        int cartTotalQuantity = 0;
        BigDecimal cartTotalPrice = BigDecimal.ZERO;
        for (Product product : productList) {
            String cartString = opsForHash.get(key, String.valueOf(product.getId()));
            if (StringUtils.isNotEmpty(cartString)) {
                Cart cart = gson.fromJson(cartString, Cart.class);
                CartProductVo cartProductVo = new CartProductVo(
                        product.getId(),
                        cart.getQuantity(),
                        product.getName(),
                        product.getSubTitle(),
                        product.getMainImage(),
                        product.getPrice(),
                        product.getStatus(),
                        product.getPrice().multiply(BigDecimal.valueOf(cart.getQuantity())),
                        product.getStock(),
                        cart.getProductSelected()
                );
                cartProductVoList.add(cartProductVo);
                //购物车中选中的商品总价
                if (cart.getProductSelected()) {
                    cartTotalPrice = cartTotalPrice.add(cartProductVo.getProductTotalPrice());
                }
                //是否全选，购物车中每一个都选中
                if (!cart.getProductSelected()) {
                    selectAll = false;
                }
                //购物车中的商品总数
                cartTotalQuantity += cart.getQuantity();
            }
        }

        cartVo.setSelectAll(selectAll);
        cartVo.setCartProductVoList(cartProductVoList);
        cartVo.setCartTotalQuantity(cartTotalQuantity);
        cartVo.setCartTotalPrice(cartTotalPrice);
        return cartVo;
    }

    @Override
    public ResponseVo<CartVo> updateCart(Integer uid, Integer productId, CartUpdateForm form) {
        //从redis里面查询出来，然后修改
        String key = String.format(MallConstants.CART_REDIS_KEY_TEMPLATE, uid);
        String cartString = opsForHash.get(key, String.valueOf(productId));
        if (StringUtils.isEmpty(cartString)) {
            return ResponseVo.error(EnumUtil.CART_PRODUCT_NOT_EXIST);
        }
        Cart cart = gson.fromJson(cartString, Cart.class);
        if (form.getQuantity() != null && form.getQuantity() >= 0) {
            cart.setQuantity(form.getQuantity());
        }
        if (form.getSelected() != null) {
            cart.setProductSelected(form.getSelected());
        }
        opsForHash.put(key,String.valueOf(productId),gson.toJson(cart));
        return cartList(uid);
    }

    @Override
    public ResponseVo<CartVo> deleteCart(Integer uid, Integer productId) {
        String key = String.format(MallConstants.CART_REDIS_KEY_TEMPLATE, uid);
        String cartString = opsForHash.get(key, String.valueOf(productId));
        if (StringUtils.isEmpty(cartString)) {
            return ResponseVo.error(EnumUtil.CART_PRODUCT_NOT_EXIST);
        }
        //hash结构如果没有数据那个key也会被删除掉
        opsForHash.delete(key, String.valueOf(productId));
        return cartList(uid);
    }

    @Override
    public ResponseVo<CartVo> selectAll(Integer uid) {
        String key = String.format(MallConstants.CART_REDIS_KEY_TEMPLATE, uid);
        List<Cart> cartList = listForCart(uid);
        cartList.forEach(cart -> {
            cart.setProductSelected(true);
            opsForHash.put(key,String.valueOf(cart.getProductId()),gson.toJson(cart));
        });
        return cartList(uid);
    }

    @Override
    public List<Cart> listForCart(Integer uid) {
        String key = String.format(MallConstants.CART_REDIS_KEY_TEMPLATE, uid);
        Map<String, String> entries = opsForHash.entries(key);
        List<Cart> cartList = new ArrayList<>();
        for (Map.Entry<String, String> entry : entries.entrySet()) {
            String cartString = entry.getValue();
            Cart cart = gson.fromJson(cartString, Cart.class);
            cartList.add(cart);
        }
        return cartList;
    }

    @Override
    public ResponseVo<CartVo> unSelectAll(Integer uid) {
        String key = String.format(MallConstants.CART_REDIS_KEY_TEMPLATE, uid);
        List<Cart> cartList = listForCart(uid);
        cartList.forEach(cart -> {
            cart.setProductSelected(false);
            opsForHash.put(key,String.valueOf(cart.getProductId()),gson.toJson(cart));
        });
        return cartList(uid);
    }

    @Override
    public ResponseVo<Integer> sum(Integer uid) {
        List<Cart> cartList = listForCart(uid);
        Integer sum = cartList.stream().map(Cart::getQuantity).reduce(0, Integer::sum);
        return ResponseVo.success(sum);
    }

}
